home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
-
- #include "parse.h"
- #include <gl.h>
- #include <math.h>
- #include <malloc.h>
-
- extern float fxmin, fxmax, fymin, fymax;
-
- short defaultwidth = 1;
- long showinvisible = 0;
- long showinfo = 1;
- long inpupdraw = 0;
-
- long setcolor(long c)
- {
- if (c == INVISIBLE) {
- if (showinvisible)
- color(8);
- else
- return 0;
- } else
- color((unsigned short)c);
- if (c == SMEAR) {
- drawmode(PUPDRAW);
- inpupdraw = 1;
- color(1);
- }
- if (c == BLINK) {
- color(255);
- }
- return 1;
- }
-
- void resetcolor()
- {
- if (inpupdraw) {
- drawmode(NORMALDRAW);
- inpupdraw = 0;
- }
- }
-
- void comment::draw()
- {
- }
-
- void text::draw()
- {
- char tstr[100];
- if (str[0] && showinfo) {
- if (0 == setcolor(Color)) return;
- sprintf(tstr, "%s", str);
- charstr(tstr);
- }
- resetcolor();
- }
-
- void comment::PostScript(FILE *fp)
- {
- }
-
- void length::PostScript(FILE *fp)
- {
- char str[100];
- if (name[0]) {
- if (INVISIBLE == Color) return;
- fprintf(fp, "(%s = %f) show\n", name, value);
- }
- }
-
- void length::draw()
- {
- char str[100];
- if (name[0]) {
- if (0 == setcolor(Color)) return;
- sprintf(str, "%s = %f", name, value);
- charstr(str);
- }
- resetcolor();
- }
-
- void vertex::draw()
- {
- float spbsize;
-
- if (w == 0.0) return;
- if (0 == setcolor(Color)) return;
- if (this == pselected) linewidth(3);
- switch (type) {
- case _diamond:
- move2(xw-pbsize, yw); draw2(xw, yw+pbsize);
- draw2(xw+pbsize, yw); draw2(xw, yw-pbsize);
- draw2(xw-pbsize, yw);
- linewidth(defaultwidth);
- pnt2(xw, yw);
- break;
- case _plus:
- move2(xw-pbsize, yw); draw2(xw+pbsize, yw);
- move2(xw, yw-pbsize); draw2(xw, yw+pbsize);
- linewidth(defaultwidth);
- pnt2(xw, yw);
- break;
- case _cross: // square, really
- spbsize = pbsize*.707107;
- move2(xw-spbsize, yw-spbsize); draw2(xw+spbsize, yw-spbsize);
- draw2(xw+spbsize, yw+spbsize); draw2(xw-spbsize, yw+spbsize);
- draw2(xw-spbsize, yw-spbsize);
- linewidth(defaultwidth);
- pnt2(xw, yw);
- break;
- case _nomark:
- break;
- case _soliddiamond:
- pmv2(xw-pbsize, yw); pdr2(xw, yw+pbsize);
- pdr2(xw+pbsize, yw); pdr2(xw, yw-pbsize);
- pdr2(xw-pbsize, yw); pclos();
- linewidth(defaultwidth);
- break;
- }
- if (name[0]) {
- cmov2(xw + pbsize/2, yw + pbsize/2);
- charstr(name);
- }
- resetcolor();
- }
-
- #define VERTEXWIDTH (0.0025)
- #define LINEWIDTH (0.0040)
-
- int infinite(float x, float y)
- {
- if(x<0.0)
- x = -x;
- if(x>2.0)
- return 1;
- if(y<0.0)
- y = -y;
- if(y>2.0)
- return 1;
- return 0;
- }
-
- double flerp(double f0,double f1,double p)
- {
- return ((f0*(1.0-p))+(f1*p));
- }
-
- int clipedge1(double *x1, double *y1, double *x2, double *y2)
- {
- float p;
-
- if(*x1<0.0 && *x2<0.0)
- return 1;
- if(*x1<0.0 && *x2>0.0) {
- p = -(*x1)/((*x2)-(*x1));
- *x1 = 0.0;
- *y1 = flerp(*y1,*y2,p);
- } else if(*x1>0.0 && *x2<0.0) {
- p = -(*x2)/((*x1)-(*x2));
- *x2 = 0.0;
- *y2 = flerp(*y2,*y1,p);
- }
- return 0;
- }
-
- int clipedge2(double *x1, double *y1, double *x2, double *y2)
- {
- if(clipedge1(x1,y1,x2,y2))
- return 1;
- *x1 = 1.0-(*x1);
- *x2 = 1.0-(*x2);
- if(clipedge1(x1,y1,x2,y2))
- return 1;
- *x1 = 1.0-(*x1);
- *x2 = 1.0-(*x2);
- return 0;
- }
-
- int clipline(double *x1, double *y1, double *x2, double *y2)
- {
- if(clipedge2(x1,y1,x2,y2))
- return 1;
- if(clipedge2(y1,x1,y2,x2))
- return 1;
- return 0;
- }
-
- void drawline(FILE *fp, float x1, float y1, float x2, float y2)
- {
- double fx1, fy1, fx2, fy2;
-
- fx1 = (x1+1.0)/2.0;
- fy1 = (y1+1.0)/2.0;
- fx2 = (x2+1.0)/2.0;
- fy2 = (y2+1.0)/2.0;
- if(clipline(&fx1,&fy1,&fx2,&fy2))
- return;
- x1 = (2.0*fx1)-1.0;
- y1 = (2.0*fy1)-1.0;
- x2 = (2.0*fx2)-1.0;
- y2 = (2.0*fy2)-1.0;
- fprintf(fp, "newpath\n");
- fprintf(fp, "%f %f moveto\n", x1, y1);
- fprintf(fp, "%f %f lineto\n", x2, y2);
- fprintf(fp, "stroke\n");
- }
-
- void setlinestyle(FILE *fp, int val)
- {
- switch(val) {
- case 0:
- fprintf(fp, "[0.020 0.010] 0 setdash\n");
- fprintf(fp, "%f setlinewidth\n",LINEWIDTH/24.0);
- break;
- case 1:
- fprintf(fp, "[] 0 setdash\n");
- fprintf(fp, "%f setlinewidth\n",LINEWIDTH);
- break;
- }
- }
-
- extern void setPScolor(long, FILE *);
-
- void vertex::PostScript(FILE *fp)
- {
- if (Color == INVISIBLE) return;
- if (w == 0.0) return;
- setlinestyle(fp,1);
- fprintf(fp, "1 setgray\n");
- fprintf(fp, "newpath\n");
- fprintf(fp, "%f %f %f 0 360 arc closepath fill\n", xw, yw, pbsize/2.0);
- setPScolor(Color, fp);
- fprintf(fp, "%f setlinewidth\n",VERTEXWIDTH);
- fprintf(fp, "newpath\n");
- fprintf(fp, "%f %f %f 0 360 arc closepath stroke\n", xw, yw, pbsize/2.0);
- if (name[0]) {
- setlinestyle(fp,1);
- fprintf(fp, "%f %f moveto\n", xw + pbsize/2, yw + pbsize/2);
- fprintf(fp, "(%s) haloshow\n",name);
- }
- }
-
- void line::draw()
- {
- float x1[2], x2[2];
-
- if (0 == setcolor(Color)) return;
- if (v1.w != 0.0 && v2.w != 0.0 && type != _longline) {
- x1[0] = v1.xw; x1[1] = v1.yw;
- x2[0] = v2.xw; x2[1] = v2.yw;
- switch (type) {
- case _ray12:
- x2[0] = x2[0] + 10000.0*(x2[0] - x1[0]);
- x2[1] = x2[1] + 10000.0*(x2[1] - x1[1]);
- break;
- case _segment:
- break;
- }
- } else {
- if (XW == 0.0 && YW == 0.0) {
- x1[0] = x2[0] = 1.0e30;
- x1[1] = x2[1] = 1.0e30;
- } else if (fabs(YW) >= fabs(XW)) {
- x1[0] = -10.0; x2[0] = 10.0;
- x1[1] = -(W + XW*x1[0])/YW;
- x2[1] = -(W + XW*x2[0])/YW;
- } else {
- x1[1] = -10.0; x2[1] = 10.0;
- x1[0] = -(W+YW*x1[1])/XW;
- x2[0] = -(W+YW*x2[1])/XW;
- }
- }
- if (this == pselected) linewidth(3);
- bgnline();
- v2f(x1);
- v2f(x2);
- endline();
- linewidth(defaultwidth);
- resetcolor();
- }
-
- void line::PostScript(FILE *fp)
- {
- float x1[2], x2[2];
-
- if (Color == INVISIBLE && showinvisible == 0) return;
- if (v1.w != 0.0 && v2.w != 0.0 && type != _longline) {
- x1[0] = v1.xw; x1[1] = v1.yw;
- x2[0] = v2.xw; x2[1] = v2.yw;
- switch (type) {
- case _ray12:
- x2[0] = x2[0] + 10000.0*(x2[0] - x1[0]);
- x2[1] = x2[1] + 10000.0*(x2[1] - x1[1]);
- break;
- case _segment:
- break;
- }
- } else {
- if (XW == 0.0 && YW == 0.0) {
- x1[0] = x2[0] = 1.0e30;
- x1[1] = x2[1] = 1.0e30;
- } else if (fabs(YW) >= fabs(XW)) {
- x1[0] = -10.0; x2[0] = 10.0;
- x1[1] = -(W + XW*x1[0])/YW;
- x2[1] = -(W + XW*x2[0])/YW;
- } else {
- x1[1] = -10.0; x2[1] = 10.0;
- x1[0] = -(W+YW*x1[1])/XW;
- x2[0] = -(W+YW*x2[1])/XW;
- }
- }
- if (Color == INVISIBLE)
- setlinestyle(fp,0);
- else
- setlinestyle(fp,1);
- drawline(fp,x1[0],x1[1],x2[0],x2[1]);
- }
-
- void bezier::draw()
- {
- float x1[2], x2[2], x3[2], x4[2], p[2], t;
-
- if (0 == setcolor(Color)) return;
- if (v1.w != 0.0 && v2.w != 0.0 && v3.w != 0.0 && v4.w != 0.0) {
- x1[0] = v1.xw; x1[1] = v1.yw;
- x2[0] = v2.xw; x2[1] = v2.yw;
- x3[0] = v3.xw; x3[1] = v3.yw;
- x4[0] = v4.xw; x4[1] = v4.yw;
- if (this == pselected) linewidth(3);
- bgnline();
- for (t = 0.0; t <= 1.001; t += .03125) {
- float t3 = t*t*t;
- float t2 = 3.0*t*t*(1.0-t);
- float t1 = 3.0*t*(1.0-t)*(1.0-t);
- float t0 = (1.0-t)*(1.0-t)*(1.0-t);
- p[0] = t0*x1[0]+t1*x2[0]+t2*x3[0]+t3*x4[0];
- p[1] = t0*x1[1]+t1*x2[1]+t2*x3[1]+t3*x4[1];
- v2f(p);
- }
- endline();
- linewidth(defaultwidth);
- }
- resetcolor();
- }
-
- float bezier::disttobezier(float x, float y)
- {
- float vmin = 1.0e30, vv;
- float x1[2], x2[2], x3[2], x4[2], p[2], t;
-
- if (v1.w != 0.0 && v2.w != 0.0 && v3.w != 0.0 && v4.w != 0.0) {
- x1[0] = v1.xw; x1[1] = v1.yw;
- x2[0] = v2.xw; x2[1] = v2.yw;
- x3[0] = v3.xw; x3[1] = v3.yw;
- x4[0] = v4.xw; x4[1] = v4.yw;
- for (t = 0.0; t <= 1.0001; t += .001) {
- float t3 = t*t*t;
- float t2 = 3.0*t*t*(1.0-t);
- float t1 = 3.0*t*(1.0-t)*(1.0-t);
- float t0 = (1.0-t)*(1.0-t)*(1.0-t);
- p[0] = t0*x1[0]+t1*x2[0]+t2*x3[0]+t3*x4[0];
- p[1] = t0*x1[1]+t1*x2[1]+t2*x3[1]+t3*x4[1];
- vv = (p[0]-x)*(p[0]-x) + (p[1]-y)*(p[1]-y);
- if (vv < vmin) vmin = vv;
- }
- }
- return sqrt(vmin);
- }
-
- void bezier::PostScript(FILE *fp)
- {
- if (Color == INVISIBLE && showinvisible == 0) return;
- if (v1.w == 0.0 || v2.w == 0.0 || v3.w == 0.0 || v4.w == 0.0) return;
- if (Color == INVISIBLE)
- setlinestyle(fp,0);
- else
- setlinestyle(fp,1);
- fprintf(fp, "newpath\n");
- fprintf(fp, "%f %f moveto\n", v1.xw, v1.yw);
- fprintf(fp, "%f %f %f %f %f %f curveto\n",
- v2.xw, v2.yw, v3.xw, v3.yw, v4.xw, v4.yw);
- fprintf(fp, "stroke\n");
- }
-
- static float *hypc = 0;
-
- void hyp()
- {
- if (hypc == 0) {
- hypc = new float[1600];
- hypc[0] = -1000000.0; hypc[1] = 1000000.0;
- hypc[399*2] = 1000000.0; hypc[399*2+1] = 1000000.0;
- hypc[400*2] = -1000000.0; hypc[400*2+1] = -1000000.0;
- hypc[799*2] = 1000000.0; hypc[799*2+1] = -1000000.0;
- for (long i = 1; i < 399; i++) {
- hypc[i*2] = hypc[(i+400)*2] = -5.0 + 10.0*(i-1)/398.0;
- hypc[i*2+1] = sqrt(1 + hypc[i*2]*hypc[i*2]);
- hypc[(i+400)*2+1] = -hypc[i*2+1];
- }
- }
- bgnline();
- for (long i = 0; i < 400; i++) v2f(&hypc[i*2]);
- endline();
- bgnline();
- for (i = 0; i < 400; i++) v2f(&hypc[(i+400)*2]);
- endline();
- }
-
- static float *circdata = 0;
-
- void cir()
- {
- if (circdata == 0) {
- circdata = new float[1600];
- for (long i = 0; i < 800; i++) {
- circdata[2*i] = cos(2.0*PI*i/800);
- circdata[2*i+1] = sin(2.0*PI*i/800);
- }
- }
- bgnclosedline();
- for (long i = 0; i < 800; i++) v2f(&circdata[2*i]);
- endclosedline();
- }
-
- // The following somewhat bizarre code is for drawing large circles.
- // For moderately large radii, a more accurate circle (500 points)
- // is drawn. For huge circles, the part of the circle intersecting
- // the viewed region is drawn as two straight lines. The lines are
- // preferentially drawn in the shorter direction, but if the
- // equations in that direction cannot be solved, the lines are drawn
- // in the longer direction (if possible).
-
- void accuratecircle(float x, float y, float radius)
- {
- float v1, v2, w1, w2;
- long flipped = 0;
-
- if (radius > 200) {
- if (fxmax - fxmin > fymax - fymin) {
- l1:
- float d = radius*radius - (fymax-y)*(fymax-y);
- if (d < 0) {
- if (flipped) return;
- flipped = 1;
- goto l2;
- }
- d = sqrt(d);
- v1 = x + d; v2 = x - d;
- d = radius*radius - (fymin-y)*(fymin-y);
- if (d < 0) {
- if (flipped) return;
- flipped = 1;
- goto l2;
- }
- d = sqrt(d);
- w1 = x + d; w2 = x - d;
- move2(v1, fymax); draw2(w1, fymin);
- move2(v2, fymax); draw2(w2, fymin);
- } else {
- l2:
- float d = radius*radius - (fxmax-x)*(fxmax-x);
- if (d < 0) {
- if (flipped) return;
- flipped = 1;
- goto l1;
- }
- d = sqrt(d);
- v1 = y + d; v2 = y - d;
- d = radius*radius - (fxmin-x)*(fxmin-x);
- if (d < 0) {
- if (flipped) return;
- flipped = 1;
- goto l1;
- }
- d = sqrt(d);
- w1 = y + d; w2 = y - d;
- move2(fxmax, v1); draw2(fxmin, w1);
- move2(fxmax, v2); draw2(fxmin, w2);
- }
- return;
- }
- pushmatrix();
- translate(x, y, 0.0);
- scale(radius, radius, radius);
- cir();
- popmatrix();
- }
-
- void drawaline(vertex *v1, vertex *v2, long selected)
- {
- float XW, YW, W, x1[2], x2[2];
-
- XW = v1->yw*v2->w - v2->yw*v1->w;
- YW = v1->w*v2->xw - v2->w*v1->xw;
- W = v1->xw*v2->yw - v1->yw*v2->xw;
- if (fabs(YW) >= fabs(XW)) {
- x1[0] = -10.0; x2[0] = 10.0;
- x1[1] = -(W + XW*x1[0])/YW;
- x2[1] = -(W + XW*x2[0])/YW;
- } else {
- x1[1] = -10.0; x2[1] = 10.0;
- x1[0] = -(W+YW*x1[1])/XW;
- x2[0] = -(W+YW*x2[1])/XW;
- }
- if (selected) linewidth(3);
- bgnline();
- v2f(x1);
- v2f(x2);
- endline();
- linewidth(defaultwidth);
- }
-
- void circle::draw()
- {
- if (0 == setcolor(Color)) return;
- if (center.w != 0.0) {
- float x = center.xw;
- float y = center.yw;
- if (this == pselected) linewidth(3);
- if (radius < 4.0)
- circ(x, y, radius);
- else
- accuratecircle(x, y, radius);
- linewidth(defaultwidth);
- } else {
- long valid1 = (v1.w != 0.0) ? 1 : 0;
- long valid2 = (v2.w != 0.0) ? 2 : 0;
- long valid3 = (v3.w != 0.0) ? 4 : 0;
- switch (valid1+valid2+valid3) {
- case 0:
- break;
- case 1: case 3: case 6: case 7:
- drawaline(&v1, &v2, this==pselected);
- break;
- case 2:
- drawaline(&v2, &v1, this==pselected);
- break;
- case 4:
- drawaline(&v3, &v1, this==pselected);
- break;
- case 5:
- drawaline(&v1, &v3, this==pselected);
- break;
- }
- }
- resetcolor();
- }
-
- void circle::PostScript(FILE *fp)
- {
- if (Color == INVISIBLE && showinvisible == 0) return;
- if (center.w != 0.0) {
- float x = center.xw;
- float y = center.yw;
-
- if (Color == INVISIBLE)
- setlinestyle(fp,0);
- else
- setlinestyle(fp,1);
- fprintf(fp, "newpath\n");
- fprintf(fp, "%f %f %f 0 360 arc closepath stroke\n", x, y, radius);
- }
- }
-
- long vertex::hitvertex(float x, float y)
- {
- if (showinvisible == 0 && Color == INVISIBLE) return 0;
- if (w == 0.0) return 0;
- if (x < xw - TOL) return 0;
- if (x > xw + TOL) return 0;
- if (y < yw - TOL) return 0;
- if (y > yw + TOL) return 0;
- return 1;
- }
-
- long line::hitline(float x, float y)
- {
- if (showinvisible == 0 && Color == INVISIBLE) return 0;
- if (disttoline(x, y) < TOL/2.0) return 1;
- return 0;
- }
-
- long conic::hitconic(float x, float y)
- {
- if (showinvisible == 0 && Color == INVISIBLE) return 0;
- if (disttoconic(x, y) < TOL) return 1;
- return 0;
- }
-
- long bezier::hitbezier(float x, float y)
- {
- if (showinvisible == 0 && Color == INVISIBLE) return 0;
- if (disttobezier(x, y) < TOL/2.0) return 1;
- return 0;
- }
-
- long circle::hitcircle(float x, float y)
- {
- if (showinvisible == 0 && Color == INVISIBLE) return 0;
- if (disttocircle(x, y) < TOL/2.0) return 1;
- return 0;
- }
-
- void vertonlineline(vertex *, line *, line *);
-
- void vertex::projecttoline(line *l)
- {
- line ll;
- ll.XW = -l->YW; ll.YW = l->XW;
- ll.W = -(xw*ll.XW + yw*ll.YW);
- vertonlineline(this, l, &ll);
- }
-
- float line::disttoline(float x, float y)
- {
- if (XW == 0.0 && YW == 0.0) return 1.0e30;
- float d = (XW*x + YW*y + W)/sqrt(XW*XW+YW*YW);
- return fabs(d);
- }
-
- float circle::disttocircle(float x, float y) // needs work XXX
- {
- float x0 = center.xw/center.w;
- float y0 = center.yw/center.w;
- float R = sqrt((x0-x)*(x0-x)+(y0-y)*(y0-y));
- R = R-radius;
- return (R >= 0.0) ? R : -R;
- }
-
- float conic::disttoconic(float x, float y)
- {
- float dist = 1.0e30, dt;
- float xval, yval, u;
-
- for (xval = fxmin; xval <= fxmax; xval += .01) {
- float a = cc;
- float b = bb*xval + ee;
- float c = aa*xval*xval + dd*xval + ff;
- if ((u = b*b - 4.0*a*c) >= 0) {
- float disc = sqrt(b*b - 4.0*a*c);
- float y1 = (-b + disc)/(2*a);
- float y2 = (-b - disc)/(2*a);
- if ((dt=(x-xval)*(x-xval)+(y1-y)*(y1-y))<dist) dist = dt;
- if ((dt=(x-xval)*(x-xval)+(y2-y)*(y2-y))<dist) dist = dt;
- }
- }
- for (yval = fymin; yval <= fymax; yval += .01) {
- float a = aa;
- float b = bb*yval + dd;
- float c = cc*yval*yval + ee*yval + ff;
- if ((u = b*b - 4.0*a*c) >= 0) {
- float disc = sqrt(b*b - 4.0*a*c);
- float x1 = (-b + disc)/(2*a);
- float x2 = (-b - disc)/(2*a);
- if ((dt=(x-x1)*(x-x1)+(y-yval)*(y-yval))<dist) dist = dt;
- if ((dt=(x-x2)*(x-x2)+(y-yval)*(y-yval))<dist) dist = dt;
- }
- }
- return sqrt(dist);
- }
-
- void conic::draw()
- {
- double theta = atan2(bb, aa-cc)/2.0;
- double Cos = cos(theta), Sin = sin(theta);
- double AA = aa*Cos*Cos + bb*Cos*Sin + cc*Sin*Sin;
- double CC = aa*Sin*Sin - bb*Cos*Sin + cc*Cos*Cos;
- double DD = dd*Cos + ee*Sin;
- double EE = ee*Cos - dd*Sin;
- double FF = ff;
- if (fabs(AA) < 5.0e-3 || fabs(CC) < 5.0e-3) { // it's a parabola
- float y, dy, x, dx, pt[2];
- if (0 == setcolor(Color)) return;
- if (this == pselected) linewidth(3);
- pushmatrix();
- rot(theta*180.0/PI, 'z');
- bgnline();
- if (fabs(AA) < 5.0e-3) {
- dy = 2*(fymax - fymin) / 80;
- for (y = fymin-20*dy; y < fymax+20*dy; y += dy) {
- x = -(CC*y*y+EE*y+FF)/DD;
- pt[0] = x;
- pt[1] = y;
- v2f(pt);
- }
- } else {
- dx = 2*(fxmax - fxmin) / 80;
- for (x = fxmin-20*dx; x < fxmax+20*dx; x += dx) {
- y = -(AA*x*x+DD*x+FF)/EE;
- pt[0] = x;
- pt[1] = y;
- v2f(pt);
- }
- }
- endline();
- popmatrix();
- linewidth(defaultwidth);
- resetcolor();
- return;
- }
- float transx = -DD/(2.0*AA), transy = -EE/(2.0*CC);
- FF = FF + AA*transx*transx + CC*transy*transy + DD*transx + EE*transy;
- AA = AA/FF; CC = CC/FF;
- // equation is now: AA*x*x + CC*y*y + 1 = 0;
- if (AA > 0.0 && CC > 0.0) return;
- if (0 == setcolor(Color)) return;
- if (this == pselected) linewidth(3);
- if (AA < 0.0 && CC < 0.0) {
- float scalex = 1.0/sqrt(-AA), scaley = 1.0/sqrt(-CC);
- pushmatrix();
- rot(theta*180.0/PI, 'z');
- translate(transx, transy, 0.0);
- scale(scalex, scaley, 1.0);
- cir();
- popmatrix();
- } else {
- float scalex, scaley;
- if (AA > 0.0) scalex = 1.0/sqrt(AA); else scalex = 1.0/sqrt(-AA);
- if (CC > 0.0) scaley = 1.0/sqrt(CC); else scaley = 1.0/sqrt(-CC);
- pushmatrix();
- rot(theta*180.0/PI, 'z');
- translate(transx, transy, 0.0);
- scale(scalex, scaley, 1.0);
- if (CC > 0.0)
- rot(90.0, 'z');
- hyp();
- popmatrix();
- }
- linewidth(defaultwidth);
- resetcolor();
- }
-
- void conic::PostScript(FILE *fp)
- {
- if (Color == INVISIBLE && showinvisible == 0) return;
- if (Color == INVISIBLE)
- setlinestyle(fp,0);
- else
- setlinestyle(fp,1);
- double theta = atan2(bb, aa-cc)/2.0;
- double Cos = cos(theta), Sin = sin(theta);
- float AA = aa*Cos*Cos + bb*Cos*Sin + cc*Sin*Sin;
- float CC = aa*Sin*Sin - bb*Cos*Sin + cc*Cos*Cos;
- float DD = dd*Cos + ee*Sin;
- float EE = ee*Cos - dd*Sin;
- float FF = ff;
- float transx = -DD/(2.0*AA), transy = -EE/(2.0*CC);
- FF = FF + AA*transx*transx + CC*transy*transy + DD*transx + EE*transy;
- AA = AA/FF; CC = CC/FF;
- // equation is now: AA*x*x + CC*y*y + 1 = 0;
- if (AA > 0.0 && CC > 0.0) return;
- if (0 == setcolor(Color)) return;
- if (this == pselected) linewidth(3);
- if (AA < 0.0 && CC < 0.0) {
- float scalex = 1.0/sqrt(-AA), scaley = 1.0/sqrt(-CC);
- fprintf(fp, "gsave\n");
- fprintf(fp, "%g rotate\n", theta*180/PI);
- fprintf(fp, "%g %g translate\n", transx, transy);
- fprintf(fp, "%g %g scale\n", scalex, scaley);
- fprintf(fp, "newpath\n");
- fprintf(fp, "0 0 1 0 360 arc closepath stroke\n");
- fprintf(fp, "grestore\n");
- } else {
- float scalex, scaley;
- if (AA > 0.0) scalex = 1.0/sqrt(AA); else scalex = 1.0/sqrt(-AA);
- if (CC > 0.0) scaley = 1.0/sqrt(CC); else scaley = 1.0/sqrt(-CC);
- fprintf(fp, "gsave\n");
- fprintf(fp, "%g rotate\n", theta*180/PI);
- fprintf(fp, "%g %g translate\n", transx, transy);
- fprintf(fp, "%g %g scale\n", scalex, scaley);
- if (CC > 0.0)
- fprintf(fp, "90 rotate\n");
- fprintf(fp, "newpath\n");
- fprintf(fp, "%g %g moveto\n", hypc[0], hypc[1]);
- for (long i = 1; i < 400; i++)
- fprintf(fp, "%g %g lineto\n", hypc[i*2], hypc[i*2+1]);
- fprintf(fp, "closepath stroke newpath\n");
- fprintf(fp, "%g %g moveto\n", hypc[400*2], hypc[400*2+1]);
- for (i = 1; i < 400; i++)
- fprintf(fp, "%g %g lineto\n", hypc[(i+400)*2], hypc[(i+400)*2+1]);
- fprintf(fp, "closepath stroke\n");
- fprintf(fp, "grestore\n");
- }
- linewidth(defaultwidth);
- resetcolor();
- }
-